package com.xujiang.common.util;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v4.content.LocalBroadcastManager;

import java.util.List;
import java.util.Map;

/**
 * 自定义广播接收器
 *
 * 1).对于静态注册的ContextReceiver，回调onReceive(context, intent)中的context具体指的是ReceiverRestrictedContext；
 * 2).对于全局广播的动态注册的ContextReceiver，回调onReceive(context, intent)中的context具体指的是Activity Context；
 * 3).对于通过LocalBroadcastManager动态注册的ContextReceiver，回调onReceive(context, intent)中的context具体指的是Application Context。
 *
 * @author xujiang
 * @version 2017-05-09 13:55
 */
public class MBroadcastReceiver extends BroadcastReceiver {

    private LocalBroadcastManager instance;
    private OnMBroadcastListener onMBroadcastListener;

    public MBroadcastReceiver(OnMBroadcastListener onMBroadcastListener){
        this.onMBroadcastListener = onMBroadcastListener;

    }


    @Override
    public void onReceive(Context context, Intent intent) {
        if(GlobalStaticVariable.BroadcastReceiverNum == 0)
            onMBroadcastListener.onReceive(context,intent);  //监听回掉
        GlobalStaticVariable.BroadcastReceiverNum = 0;  //只忽略一次
    }

    /**
     * 发送广播
     *
     * @param context 上下问对象用于发送广播
     * @param action 定义这个广播的string，每个广播都需要一个唯一的string标识
     * @param map 广播里携带的值
     * @param receiverPermission 广播权限
     * 使用广播权限要注意，首先 从一个app发送带权限的广播到另一个app
     * 假设 张三发送给李四，李四发送给王五
     * 第一个 张三发送给李四
     * 1、在李四的AndroidManifest.xml中声明如下权限
     *
     * 需要注意的是，在声明权限时需要一个android:protectionLevel的属性，它代表“风险级别”。必须是以下值之一：
     * normal、dangerous、signature、signatureOrSystem。
     * normal表示权限是低风险的，不会对系统、用户或其他应用程序造成危害。
     * dangerous表示权限是高风险的，系统将可能要求用户输入相关信息，才会授予此权限。
     * signature告诉Android，只有当应用程序所用数字签名与声明此权限的应用程序所有数字签名相同时，才能将权限授给它。
     * signatureOrSystem告诉Android，将权限授给具有相同数字签名的应用程序或Android包类，这一级别适用于非常特殊的情况，比如多个供应商需要通过系统影像共享功能时。
     * 另外一个是android:permissionGroup属性，表示一个权限组。可以将权限放在一个组中，但对于自定义权限，应该避免设置此属性。如果确实希望设置此属性，
     * 可以使用以下属性代替：android.permission-group.SYSTEM_TOOLS。
     *
     * <permission android:protectionLevel="normal"  
     * android:name="scott.permission.MY_CALL_PHONE"/>  //字符串可以随便取，但建议看下权限命名规则和习惯
     * <application ...
     * 2、在李四APP中的xml中静态注册或在代码中动态注册带权限的Receiver。
     * <receiver android:name=".MyBroadcastReceiver"
     * android:permission="com.ctrlz.www">
     * <intent-filter>
     * <action
     * android:name="com.ctrlz.www"/>
     * </intent-filter>
     * </receiver>
     * 3、在张三APP的Mainfest文件中添加：
     * <uses-permission android:name="com.ctrlz.www"/>
     * 4、在张三的APP发送普通广播即可：
     *
     * 第二种情况
     *
     * 1.在李四的APP中，声明如下权限：
     * <permission android:name="com.baidu.www"/>1
     * 2.在李四APP中发送时添加如下权限：
     * sendBroadcast(intent, "com.baidu.www");
     * 3.在王五的APP中声明如下权限：
     * <uses-permission android:name="com.baidu.www"/>1
     *
     * sendBroadcastAsUser(intent, userHandler)/sendBroadcastAsUser(intent, userHandler,receiverPermission)。这两个发送广播的方法为多用户
     * 而设计，暂时不用管
     */
    public void sendBroadcast(Context context, String action, Map<String, String> map, String receiverPermission) {
        Intent intent = new Intent();
        intent.setAction(action);
        for (Map.Entry<String, String> entry : map.entrySet()) {
            intent.putExtra(entry.getKey(), entry.getValue());
        }
        if (receiverPermission != null) {
            context.sendBroadcast(intent, receiverPermission);  //带权限的广播发送
        } else {
            context.sendBroadcast(intent);
        }

    }

    /**
     * 普通广播
     */
    public void sendBroadcast(@NonNull Context context, @NonNull String action, Map<String, String> map) {
        sendBroadcast(context, action, map, null);
    }

    /**
     * 广播注册
     *
     * @param mBroadcastReceiver 我的广播接收器
     * @param intentFilter 过滤器 定义哪些action可以通过
     */
    public void registerBroadcastReceiver(@NonNull Context context, @NonNull MBroadcastReceiver mBroadcastReceiver,
            IntentFilter intentFilter) {
        context.registerReceiver(mBroadcastReceiver, intentFilter);
    }

    /**
     * 广播注册
     *
     * @param list 广播可以接受的action列表，及广播可以接受哪些action
     */
    public void registerBroadcastReceiver(@NonNull Context context, @NonNull MBroadcastReceiver mBroadcastReceiver,
            List<String> list) {
        IntentFilter intentFilter = new IntentFilter();
        for (String action : list) {
            intentFilter.addAction(action);
        }
        registerBroadcastReceiver(context, mBroadcastReceiver, intentFilter);
    }

    /**
     * 带权限的广播注册
     *
     * @param broadcastPermission 权限，与上面的权限发送配合使用
     * @param scheduler 指定线程，如果为null则在主线程执行
     */
    public void registerBroadcastReceiver(@NonNull Context context, @NonNull MBroadcastReceiver mBroadcastReceiver,
            @NonNull IntentFilter intentFilter, String broadcastPermission, Handler scheduler) {
        context.registerReceiver(mBroadcastReceiver, intentFilter, broadcastPermission, scheduler);
    }

    /**
     * 取消注册
     */
    public void unregisterReceiver(@NonNull Context context, @NonNull MBroadcastReceiver mBroadcastReceiver) {
        context.unregisterReceiver(mBroadcastReceiver);
    }

    /**
     * 注册app应用内广播（此处的App应用以App应用进程为界）
     */
    public void internalRegisterBroadcastReceiver(Context context, MBroadcastReceiver mBroadcastReceiver,
            IntentFilter intentFilter) {
        instance = LocalBroadcastManager.getInstance(context);
        instance.registerReceiver(mBroadcastReceiver, intentFilter);
    }

    /**
     * app应用内广播取消注册
     */
    public void internalUnregisterReceiver(@NonNull Context context, @NonNull MBroadcastReceiver mBroadcastReceiver) {
        instance.unregisterReceiver(mBroadcastReceiver);
    }

    /**
     * 发送应用内的广播
     */
    public void internalSendBroadcast(Intent intent) {
        instance.sendBroadcast(intent);
    }

    /**
     * 应用内的广播发送
     */
    public void internalSendBroadcast(String action, Map<String, String> map) {
        Intent intent = new Intent();
        intent.setAction(action);
        for (Map.Entry<String, String> entry : map.entrySet()) {
            intent.putExtra(entry.getKey(), entry.getValue());
        }
        internalSendBroadcast(intent);
    }

    public interface OnMBroadcastListener{
        public void onReceive(Context context,Intent intent);
    }

}
